#!/usr/bin/perl

######################################################################
package Swignition::Namespace;
######################################################################

use strict;

sub new
{
	my $class = shift;
	my ($prefix, $uri, $title, $scope, $loose) = @_;
	my $this;
	
	$this = {
		prefix  => $prefix,
		uri     => $uri,
		title   => $title,
		scope   => $scope,
		loose   => $loose
	};
	
	bless $this, $class;
}


sub bestMatch
{
	my $prefix    = shift;
	my $xpath     = shift;	
	my $bestMatch = undef;
	my $highScore = -10;
	
	foreach my $ns (@_)
	{
		my $nsScore = -11;
		if ( ($ns->{scope}<0) || (!defined $ns->{scope}) )
		{
			if ($ns->{loose} && (lc($ns->{prefix}) eq lc($prefix)))
			{
				$nsScore = (defined $ns->{scope}) ? 0 : -2;
			}
			elsif ($ns->{prefix} eq $prefix)
			{
				$nsScore = (defined $ns->{scope}) ? 1 : -1;
			}
		}
		elsif ( (length $xpath)
		&& (substr($xpath,0,(length $ns->{scope})) eq $ns->{scope}) )
		{
			if ($ns->{loose} && (lc($ns->{prefix}) eq lc($prefix)))
			{
				$nsScore = length $ns->{scope};
			}
			elsif ($ns->{prefix} eq $prefix)
			{
				$nsScore = length $ns->{scope};
			}
		}
		
		if ($nsScore > $highScore)
		{
			$highScore = $nsScore;
			$bestMatch = $ns;
		}
	}
	
	return $bestMatch;
}


sub equiv
{
	my $existing = shift;
	my $new      = shift;
	
	if ($existing->{loose})
	{
		return 0 if (lc($existing->{prefix}) ne lc($new->{prefix}));
	}
	else
	{
		return 0 if ($existing->{prefix} ne $new->{prefix});
	}
	
	return 0 if ($existing->{uri} ne $new->{uri});
	return 1 if (!defined $existing->{scope});
	return 1 if ($existing->{scope} == -1);
	
	return 1
		if (((length $existing->{scope}) < (length $new->{scope}))
		&&  substr($new->{scope}, 0, (length $existing->{scope})) eq $existing->{scope});
		
	return 0;
}


sub to_curie
{
	my $page  = shift;
	my $uri   = shift;
	my $force = shift || 0;
	my $join  = shift || ':';
	my ($start, $end);
	
	# Angle bracket delimiters should be removed.
	$uri = $1
		if ($uri =~ /^\<(URL\:\s*)?(.*)\>$/i);
	
	# Split into beginning and end bits.
	if ($uri =~ /^(.*[\#\/\?\=\:])([^\#\/\?\=\:]+)$/)
	{
		$start = $1;
		$end   = $2;
	}
	else
	{
		return;
	}
	
	# The easy case: a namespace is already defined, matching $start
	return $page->{NamespacePrefixes}->{$start}.$join.$end
		if (defined $page->{NamespacePrefixes}->{$start});
		
	# Otherwise do complex stuff.
	my $preferred_pfx;
	foreach my $ns (@{ $page->{Namespaces} })
	{
		$preferred_pfx = $ns->{prefix}
			if ($ns->{uri} eq $start);
	}
	
	if ($force)
	{
		$preferred_pfx = 'p'
			unless ($preferred_pfx);
	}
	
	if ($preferred_pfx)
	{
		my $i = 0;
		my $pfx = $preferred_pfx;
		while (defined $page->{NamespacePrefixesReverse}->{$pfx})
			{ $pfx = $preferred_pfx . $i++; }

		$page->{NamespacePrefixesReverse}->{$pfx} = $start;
		$page->{NamespacePrefixes}->{$start}      = $pfx;

		return $pfx.$join.$end;
	}
	
	return undef;
}


1;
